/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022.
 * Description: provide threshold for IMA measurement list
 * Author: xiongshenglan <xiongshenglan@huawei.com>
 * Create: 2022-09-20
 */
#include "rtos_ima_measure_threshold.h"

DEFINE_MUTEX(ima_threshod_mutex);

static atomic_long_t ima_measurements_size = ATOMIC_LONG_INIT(0);

static void set_measurements_size(long long size)
{
	atomic_long_set(&ima_measurements_size, size);
	return;
}

static long long get_measurements_size(void)
{
	return atomic_long_read(&ima_measurements_size);
}

bool ima_compare_measurement_threshold(void)
{
	long long current_measurements = atomic_long_read(&ima_htable.len);
	long long set_threshold = get_measurements_size();
	if (set_threshold <= 0)
		return true;
	return current_measurements < set_threshold;
}

static bool valid_threshold = true;
struct dentry *ima_measurement_threshold;

static ssize_t ima_write_threshold(struct file *filp, const char __user *buf,
				size_t datalen, loff_t *ppos)
{
	ssize_t result;
	long long ima_set_threshold;
	long long current_len;

	result = mutex_lock_interruptible(&ima_threshod_mutex);
	if (result < 0)
		return -EBUSY;

	if (*ppos != 0 || !valid_threshold) {
		result  = -EINVAL;
		goto out;
	}

	result = kstrtou64_from_user(buf, datalen, 10, &ima_set_threshold);
	if (result < 0)
		goto out;

	current_len = atomic_long_read(&ima_htable.len);
	if (ima_set_threshold <= 0 || ima_set_threshold <= current_len) {
		result = -EINVAL;
		goto out;
	}
	set_measurements_size(ima_set_threshold);
	valid_threshold = false;
	result = datalen;
out:
	mutex_unlock(&ima_threshod_mutex);
	return result;
}

const struct file_operations ima_measurement_threshold_ops = {
	.write = ima_write_threshold,
	.llseek = generic_file_llseek,
};
